package main.工具.类生成器;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Map;

import javax.xml.stream.XMLStreamException;

import main.工具.解析.XML.ClassTranslation;
import main.工具.解析.XML.ClassTranslationParser;
import main.工具.解析.XML.Translation;

import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier.ModifierKeyword;
import org.eclipse.jdt.core.dom.PackageDeclaration;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.TypeParameter;

public class 汉化类源码生成器 {

  private static final AST ast = AST.newAST(AST.JLS8);
  
  public static void 源码生成(ClassTranslation 类汉化描述)
      throws IOException, ClassNotFoundException {
    String 源包路径 = getClassPath(类汉化描述, true);
    String 汉化包路径 = getClassPath(类汉化描述, false);

    String 源类路径 = 源包路径 + "." + 类汉化描述.getClassName().getEn();
    String 汉化类路径 = 汉化包路径 + "." + 类汉化描述.getClassName().getCn();
    
    CompilationUnit cu = ast.newCompilationUnit();
    PackageDeclaration p1 = ast.newPackageDeclaration();
    p1.setName(ast.newName(汉化包路径));
    cu.setPackage(p1);
    
    TypeDeclaration td = ast.newTypeDeclaration();
    td.setName(ast.newSimpleName(类汉化描述.getClassName().getCn()));
    TypeParameter tp = ast.newTypeParameter();
    tp.setName(ast.newSimpleName("X"));
    td.typeParameters().add(tp);
    cu.types().add(td);


        
    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    Class 源类 = classloader.loadClass(源类路径);

    // 封装源类的一个对象
    SingleVariableDeclaration sourceObject = ast.newSingleVariableDeclaration();
    sourceObject.setName(ast.newSimpleName("对象"));
    // TODO: add it to class field
    
    Method[] 源方法 = 源类.getMethods();
    
    // TODO: 构造方法，依赖于源类的构造方法
    
    Map<String, String> 方法汉化映射 = 类汉化描述.getMethods();
    for (String 源方法名 : 方法汉化映射.keySet()) {
      Method 源方法之一 = 按名称获取方法(源方法, 源方法名);
      
      // 只包括公用方法，接口也许不同
      if ((源方法之一.getModifiers()  & Modifier.PUBLIC) ==0) {
        return;
      }
      
      Class 返回类型 = 源方法之一.getReturnType();
      
      MethodDeclaration md = ast.newMethodDeclaration();
      md.setName(ast.newSimpleName(源方法之一.getName()));
      md.modifiers().add(ast.newModifier(ModifierKeyword.PUBLIC_KEYWORD));
      
      td.bodyDeclarations().add(md);

      Block block = ast.newBlock();
      md.setBody(block);

      MethodInvocation mi = ast.newMethodInvocation();
      mi.setName(ast.newSimpleName("x"));

      ExpressionStatement e = ast.newExpressionStatement(mi);
      block.statements().add(e);
      
      /*JMethod m = dc.method(JMod.PUBLIC, 返回类型, 方法汉化映射.get(源方法名));
      for (Parameter 方法参数 : 源方法之一.getParameters()) {
        
        // TODO: 在XML中添加参数汉化
        m.param(方法参数.getType(), 方法参数.getName());
      }
      
      // 生成返回语句。如果返回类型为void，无return关键词
      // 例：return 对象.addAll(索引, 集合); 或当void：对象.add(索引, 元素);
      JInvocation invoke;
      if (返回类型 == Void.TYPE) {
        invoke = m.body().invoke(源对象, 源方法名);
        添加方法参数(invoke, m.params());
      } else {
        invoke = 源对象.invoke(源方法名);
        添加方法参数(invoke, m.params());
        m.body()._return(invoke);
      }*/
    }

    System.out.println(cu);
    /*
    File dir2 = new File(".");
    File file = new File(dir2.getAbsolutePath() + "/src");
    file.mkdirs();
    cm.build(file);*/
  }
/*
  private static void 添加方法参数(JInvocation 调用, List<JVar> 参数) {
    for (JVar 参数之一 : 参数) {
      
      // TODO: 在XML中添加参数汉化
      调用.arg(参数之一);
    }
  }
*/
  public static void main(String[] args) {
    List<ClassTranslation> classes;
    try {
      classes = ClassTranslationParser.parse("translationArrayList.xml");
      for (ClassTranslation classTranslation : classes) {
        源码生成(classTranslation);
      }
    } catch (XMLStreamException | ClassNotFoundException | IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
    }
  }
  
  /**
   * 
   * @param classTranslation
   * @param isEn true will generate EN classpath, false will return CN classpath
   * @return
   */
  static String getClassPath(ClassTranslation classTranslation, boolean isEn) {
    List<Translation> packages = classTranslation.getPackages();
    
    String classPath = "";
    for(int i = 0; i< packages.size(); i++) {
      classPath += isEn ? packages.get(i).getEn() : packages.get(i).getCn();
      if (i != packages.size() - 1) {
        classPath += ".";
      }
    }
    return classPath;
  }

  // TODO: 根据不同method signature，获取对应的返回类型
  static Method 按名称获取方法(Method[] methods, String methodName) {
    for (Method method : methods) {
      if (method.getName().equals(methodName)) {
        return method;
      }
    }
    return null;
  }
}
